<?php

if( ! defined('DOCROOT') )
{
    require_once '/var/www/advancelab/chilik2/unittest/bootstrap.php';
}

require __DIR__.'/../source/constructor.php';

class InstancesTest extends UnitTestCase
{
    protected $start;
    protected $mem;
    
    function setUp()
    {
        $this->start = microtime( TRUE );
        $this->mem = memory_get_usage();
    }
    
    function testingSetUp()
    {
        ob_start();
        
        $instance = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        /* dump( $instance ); */
        
        $this->assertTrue( $instance instanceof Constructor\Instances );
        
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingCtorSuccess()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        $this->assertNotNull( $instances );
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingGetSuccess()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        $test = $instances->get( 'NoDependencies' );
        
        $this->assertNotNull( $test );
        $this->assertTrue( $test instanceof NoDependencies );
        $this->assertEqual( new NoDependencies(), $test );
        
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingGetFailure()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        $test = array( NULL, TRUE, FALSE, 88, 88.99, array(), new stdClass );
        
        foreach( $test as $val )
        {
            try
            {
                $object = $instances->get( $val );
                $this->fail( 'Expected exception was not thrown.' );
            }
            catch( \Exception $e )
            {
                $this->assertEqual( 'Constructor\BaseValueException', get_class( $e ) );
            }
        }
        
        try
            {
                $object = $instances->get( '' );
                $this->fail( 'Expected exception was not thrown.' );
            }
            catch( \Exception $e )
            {
                $this->assertEqual( 'Constructor\FactoryUndefinedClassException', get_class( $e ) );
            }
        
        try
        {
            $object = $instances->get( 'NonExistentClass' );
            $this->fail( 'Expected exception was not thrown.' );
        }
        catch( \Exception $e )
        {
            $this->assertEqual( 'Dispatcher\Exception', get_class( $e ) );
        }
        
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingInstancesCount()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        $test = $instances->get( 'stdClass' );
        
        $this->assertNotNull( $test );
        $this->assertEqual( 1, $instances->count() );
        
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingInstancesGetIdentifiers()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        $test = $instances->get( 'stdClass' );
        
        $expected = array (
          0 => 'stdClass',
        );
        
        /* dump( var_export( $instances->getIdentifiers(), TRUE ) ); */
        
        $this->assertEqual( $expected, $instances->getIdentifiers() );
        
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingInstancesSetSuccess()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        $test = $instances->set( new stdClass );
        $this->assertTrue( $test );
        
        $test = $instances->set( new stdClass, 'test' );
        $this->assertTrue( $test );
        
        $this->assertTrue( $instances->has( 'stdClass' ) );
        $this->assertTrue( $instances->has( 'test' ) );
        
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingInstancesSetFailure()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        $test = array( NULL, TRUE, FALSE, 88, 88.99, '', array() );
        $test2 = array( NULL, TRUE, FALSE, 88, 88.99, '', array(), new stdClass() );
        
        foreach( $test as $val )
        {
            try
            {
                $object = $instances->set( $val );
                $this->fail( 'Expected exception was not thrown.' );
            }
            catch( \Exception $e )
            {
                $this->assertEqual( 'Constructor\BaseValueException', get_class( $e ) );
            }
            
            foreach( $test2 as $val2 )
            {
                try
                {
                    $object = $instances->set( $val, $val2 );
                    $this->fail( 'Expected exception was not thrown.' );
                }
                catch( \Exception $e )
                {
                    $this->assertEqual( 'Constructor\BaseValueException', get_class( $e ) );
                }
            }
        }
        
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingInstancesHasSuccess()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        $test = $instances->set( new stdClass );
        $this->assertTrue( $test );
        $this->assertTrue( $instances->has( 'stdClass' ) );
        
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingInstancesHasFailure()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        $test = array( NULL, TRUE, FALSE, 88, 88.99, array(), new stdClass() );
        
        foreach( $test as $val )
        {
            try
            {
                $object = $instances->has( $val );
                $this->fail( 'Expected exception was not thrown.' );
            }
            catch( \Exception $e )
            {
                $this->assertEqual( 'Constructor\BaseValueException', get_class( $e ) );
            }
        }
        
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingInstancesReset()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        $test = $instances->get( 'stdClass' );
        $test = $instances->set( new NoDependencies(), 'test' );
        $this->assertEqual( 2, $instances->count() );
        
        $instances->reset();
        $this->assertEqual( 0, $instances->count() );
        
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingInstancesCreateSuccess()
    {
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        $object = $instances->create( 'NoDependencies' );
        
        $this->assertEqual( new NoDependencies, $object );
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
    }
    
    function testingInstancesCreateFailure()
    {
        $test = array( TRUE, FALSE, 88, 88.99, array(), new \stdClass()  );
        
        $instances = new Constructor\Instances( new Constructor\Factory(), new Constructor\Container() );
        
        foreach( $test as $val )
        {
            try
            {
                $instances->create( $val );
                $this->fail( 'Expected exception was not thrown' );
            }
            catch( \Exception $e )
            {
                $this->assertEqual( 'Constructor\BaseValueException', get_class( $e ) );
            }
        }
        
        try
        {
            $instances->create( 'NonExistentClass' );
            $this->fail( 'Expected exception was not thrown' );
        }
        catch( \Exception $e )
        {
            $this->assertEqual( 'Dispatcher\Exception', get_class( $e ) );
        }
    
        $this->dump( __METHOD__.' >> Elapsed: '.round( ( microtime( 'time' ) - $this->start ), 3).' Memory Used: '.( (memory_get_usage() - $this->mem )/ 1024 ).' KB' );
        
        //ob_end_clean();
    }
}
